import struct
import random

rounds = 12
roundKeys = 2 * (rounds + 1)

def crack(text: str) -> str:
    name = text.encode('utf-8')
    length = len(name) + 4
    padded = ((-length) & (8 - 1)) + length
    bs = struct.pack('>I', len(name))
    buff = bytearray()
    buff.extend(bs)
    buff.extend(name)

    ckName = 0x7a21c951691cd470
    ckKey = -5408575981733630035
    ck = new_ck_cipher(ckName)
    outBuff = bytearray()

    for i in range(0, padded, 8):
        bf = buff[i:i+8]
        now_var, = struct.unpack('>Q', bf)
        dd = ck.encrypt(now_var)
        outBuff.extend(struct.pack('>Q', dd))

    n = 0
    for b in outBuff:
        n = rotate_left(n ^ b, 0x3)
    prefix = n ^ 0x54882f8a
    suffix = random.randint(-(1 << 31), (1 << 31) - 1)

    if suffix >> 16 == 0x0401 or suffix >> 16 == 0x0402 or suffix >> 16 == 0x0403:
        in_ = (prefix << 32) | suffix
    else:
        in_ = (prefix << 32) | 0x01000000 | (suffix & 0xffffff)

    out = new_ck_cipher(ckKey).decrypt(in_)

    n2 = 0
    for i in range(56, -1, -8):
        n2 ^= (in_ >> i) & 0xff

    vv = n2 & 0xff
    if vv < 0:
        vv = -vv

    return f'{vv:02x}{out:016x}'

class ckCipher:
    def __init__(self):
        self.rk = [0] * roundKeys

    def encrypt(self, in_: int) -> int:
        a = (in_ & 0xffffffff) + self.rk[0]
        b = (in_ >> 32) + self.rk[1]

        for r in range(1, rounds+1):
            a = rotate_left(a ^ b, b) + self.rk[2*r]
            b = rotate_left(b ^ a, a) + self.rk[2*r+1]

        return ((b & 0xffffffff) << 32) | (a & 0xffffffff)

    def decrypt(self, in_: int) -> int:
        a = in_ & 0xffffffff
        b = in_ >> 32

        for i in range(rounds, 0, -1):
            a = rotate_right(a ^ b, b) ^ self.rk[2*i]
            b = rotate_right(b ^ a, a) ^ self.rk[2*i+1]

        a -= self.rk[0]
        b -= self.rk[1]

        return ((b & 0xffffffff) << 32) | (a & 0xffffffff)

def new_ck_cipher(ckKey: int) -> ckCipher:
    ck = ckCipher()

    ld = [0] * 2
    ld[0] = ckKey & 0xffffffff
    ld[1] = ckKey >> 32

    ck.rk[0] = -1209970333
    for i in range(1, roundKeys):
        ck.rk[i] = ck.rk[i-1] + -1640531527

    a = b = 0
    j = 0

    for k in range(3*roundKeys):
        ck.rk[a] = rotate_left(ck.rk[a] + (a+b), 3)

        ld[j] = rotate_left(ld[j] + (a+b), a+b)
        b = ld[j]

        a = (a+1) % roundKeys
        j = (j+1) % 2

    return ck

def rotate_left(x: int, y: int) -> int:
    return ((x << (y & 31)) | (x >> (32 - (y & 31)))) & 0xffffffff

def rotate_right(x: int, y: int) -> int:
    return ((x >> (y & 31)) | (x << (32 - (y & 31)))) & 0xffffffff

name = "charles"
print("name:", name, "    key:", crack(name))
